package com.hornsun.config;

import com.hornsun.config.ConfigInfo;
import com.hornsun.config.ConfigListInfo;
import com.hornsun.config.IRedisService;
import com.hornsun.data.constant.error.CommonError;
import com.hornsun.data.constant.types.Terminal;
import com.hornsun.data.dbo.AccountInfo;
import com.hornsun.data.dbo.Client;
import com.hornsun.data.dbo.ClientInfo;
import com.hornsun.data.repository.ClientRepository;
import com.hornsun.data.repository.RoleRepository;
import com.hornsun.data.repository.mapper.ResourceMapper;
import com.hornsun.util.DESUtil;
import com.hornsun.util.SerializeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;


/**
 * Created by 编译中... on 2018/5/22.
 */

@Configuration
@ComponentScan("com.hornsun")
public class WebSecurityConfig extends WebMvcConfigurationSupport {

    @Autowired
    private ConfigInfo configInfo;

    @Autowired
    private ConfigListInfo configListInfo;

    @Autowired
    private ClientRepository clientRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private IRedisService service;

    @Autowired
    private ResourceMapper resourceMapper;


    @Bean
    public WebAdminInterceptor getWebAdminInterceptor() {
        return new WebAdminInterceptor();
    }

    @Bean
    public PermissionInterceptor getPermissionInterceptor(){
        return new PermissionInterceptor();
    }



    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("/img/**").addResourceLocations("file:E:/Collaborative/image/");
        super.addResourceHandlers(registry);
    }


    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        //排除的路径

       /* addInterceptor.excludePathPatterns("/admin*//**");*/

        //拦截所有路径
        List<String> webUrl = configListInfo.getWeb();
        List<String> permissionUrl = configListInfo.getPermission();
        for (String url : webUrl){
            registry.addInterceptor(getWebAdminInterceptor()).addPathPatterns(url);
        }
        for (String url : permissionUrl){
            registry.addInterceptor(getPermissionInterceptor()).addPathPatterns(url);
        }

    }

    private class WebAdminInterceptor extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
            String param = request.getHeader("terminal");
            if (param==null||param.isEmpty()){
                response.setStatus(CommonError.NOT_LOGIN.getCode());
                return false;
            }
            HttpSession session = request.getSession();
            Terminal terminal = Terminal.getByType(Integer.parseInt(param));
            switch (terminal){
                case WEB :
                    String account = (String) session.getAttribute("Account");
                    if (account!= null&&!account.isEmpty()){
                        Client client = clientRepository.getByAccount(account);
                        if(client==null){
                            session.invalidate();
                            response.setStatus(CommonError.NOT_LOGIN.getCode());
                            return false;
                        }
                        try {
                            String initialPassword = DESUtil.encrypt(configInfo.getInitialPassword());
                            if (initialPassword.equals(client.getPassword())){
                                session.invalidate();
                                response.setStatus(CommonError.NOT_LOGIN.getCode());
                                return false;
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                        response.setHeader("Cache-Control","no-cache");
                        response.setIntHeader("permission",roleRepository.getPermission(client.getRoleGuid()));
                        return true;
                    }else {
                        response.setStatus(CommonError.NOT_LOGIN.getCode());
                        return false;
                    }
                case CLIENT_SIDE :
                    String username = request.getHeader("username");
                    String macUrl = request.getHeader("macUrl");
                    if (service.isKeyExists(configInfo.getRedisAccount(),username)) {
                        byte[] clientInfoBytes = (byte[]) service.get(configInfo.getRedisAccount(), username);
                        ClientInfo clientInfos = (ClientInfo) SerializeUtils.deSerialize(clientInfoBytes);
                        boolean hasLogin = false;
                        List<AccountInfo> accountInfoList1 = clientInfos.getAccountInfoList();
                        for (AccountInfo accountInfo : accountInfoList1) {
                            if (accountInfo.getMac().equals(macUrl)) {
                                hasLogin = true;
                                break;
                            }
                        }
                        if (hasLogin) {
                            session.setAttribute("Account",username);
                            return true;
                        } else {
                            response.setStatus(CommonError.NOT_LOGIN.getCode());
                            return false;
                        }
                    }else {
                        response.setStatus(CommonError.NOT_LOGIN.getCode());
                        return false;
                    }

                default:
                    response.setStatus(CommonError.NOT_LOGIN.getCode());
                    return false;
            }

        }
    }

    private class PermissionInterceptor extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
            HttpSession session = request.getSession();
            String account = (String) session.getAttribute("Account");
            if (account != null && !account.isEmpty()) {
                Client client = clientRepository.getByAccount(account);
                if (client == null) {
                    session.invalidate();
                    response.setStatus(CommonError.NOT_LOGIN.getCode());
                    return false;
                }
                String httpUrl = request.getRequestURI();
                String url = httpUrl.substring(0,httpUrl.lastIndexOf("/"));
                if(!service.isKeyExists(configInfo.getRedisPermission(),url)){
                    Integer sign = resourceMapper.getPermissionByUrl(url);
                    if (sign==null){
                        response.setStatus(CommonError.NO_PERMISSION.getCode());
                        return false;
                    }
                    service.put(configInfo.getRedisPermission(),url,sign,-1);
                }
                int permissionSign = (int)service.get(configInfo.getRedisPermission(),url);
                int permission = roleRepository.getPermission(client.getRoleGuid());
                if ((permission&permissionSign)==0){
                    response.setStatus(CommonError.NO_PERMISSION.getCode());
                    return false;
                }
            }else {
                response.setStatus(CommonError.NOT_LOGIN.getCode());
                return false;
            }
            return true;
        }
    }




}
